package com.toe.sso.security.service.admin.impl;

import com.toe.common.exception.ToeServiceException;
import com.toe.common.pojo.domain.ToeAuthenticationInfo;
import com.toe.common.restful.StateEnum;
import com.toe.common.utils.JwtTokenUtils;
import com.toe.sso.pojo.domain.AdminUserDetails;
import com.toe.sso.pojo.dto.AdminLoginDTO;
import com.toe.sso.security.service.admin.AdminSSOUserDetailsService;
import com.toe.sso.security.service.admin.IAdminSSOService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>管理员单点登录业务</p>
 */
// @DubboService注解表示当前业务逻辑层实现类中的所有方法
// 均会注册到Nacos,成为Dubbo可以被发现的业务逻辑层方法
@Service
@Slf4j
public class AdminSSOServiceImpl implements IAdminSSOService {
    @Autowired
    private AdminSSOUserDetailsService userDetailsService;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Override
    public String doLogin(AdminLoginDTO adminLoginDTO){
        //生成返回的token
        log.info("开始执行平台管理员login业务");
        String token = "";
        AdminUserDetails userDetails = (AdminUserDetails) userDetailsService.loadUserByUsername(adminLoginDTO.getPhone());
        log.info("转换得到的userDetails是:"+userDetails);
        if (userDetails == null) {
            log.error("登录失败!用户名密码错误");
            throw new ToeServiceException(StateEnum.ERR_PASSWORD, "登录失败！用户名错误");
        }
        if (!passwordEncoder.matches(adminLoginDTO.getPassword(), userDetails.getPassword())) {
            log.error("登录失败!用户名密码错误");
            throw new ToeServiceException(StateEnum.ERR_PASSWORD, "登录失败！密码错误");
        }
        //将UserDetails转换成自定义的封装验证类型
        log.info("将userDetails封装成我们自定义的封装验证类型");
        ToeAuthenticationInfo AuthenticationInfo = generateFromAdmin(userDetails);
        log.info("自定义的封装验证数据是:"+AuthenticationInfo);
        log.info("开始生成token");
        token = jwtTokenUtils.generateToken(AuthenticationInfo);
        log.info("token的结果是:"+token);
        return token;
    }

    @Override
    public String doLogin2(AdminLoginDTO adminLoginDTO) {
        //生成返回的token
        log.info("开始执行平台管理员login业务");
        String token = "";
        AdminUserDetails userDetails = (AdminUserDetails) userDetailsService.loadUserByUsername(adminLoginDTO.getPhone());
        log.info("转换得到的userDetails是:"+userDetails);
        if (userDetails == null) {
            log.error("登录失败!用户名密码错误");
            throw new ToeServiceException(StateEnum.ERR_PASSWORD, "登录失败！用户名错误");
        }
        //和验证进行比较
        String key = "code:item:"+adminLoginDTO.getPhone();
        Serializable serializable = redisTemplate.opsForValue().get(key);
        if (serializable==null){
            throw new ToeServiceException(StateEnum.ERR_PASSWORD, "登录失败！验证码已过期");
        }
        String code = (String) serializable;
        if (!code.equals(adminLoginDTO.getPassword())){
            throw new ToeServiceException(StateEnum.ERR_PASSWORD, "登录失败！验证码错误");
        }
        log.info("将userDetails封装成我们自定义的封装验证类型");
        ToeAuthenticationInfo AuthenticationInfo = generateFromAdmin(userDetails);
        log.info("自定义的封装验证数据是:"+AuthenticationInfo);
        log.info("开始生成token");
        token = jwtTokenUtils.generateToken(AuthenticationInfo);
        log.info("token的结果是:"+token);
        return token;
    }

    public ToeAuthenticationInfo generateFromAdmin(AdminUserDetails userDetails){
        List<GrantedAuthority> authorities = (List<GrantedAuthority>) userDetails.getAuthorities();
        List<String> authorityValues=new ArrayList<>();
        for (GrantedAuthority authority : authorities) {
            String value=authority.getAuthority();
            authorityValues.add(value);
        }
        ToeAuthenticationInfo userInfo=new ToeAuthenticationInfo();
        userInfo.setId(userDetails.getId());
        userInfo.setUsername(userDetails.getUsername());
        userInfo.setUserType("ADMIN");
        userInfo.setAuthorities(authorityValues);
        return userInfo;
    }

    @Value("${jwt.tokenHead}")
    private String tokenHead;//Bearer
    @Override
    public void doLogout(String token){

    }
}
